/*
 * SocketTCP.cpp
 *
 *  Created on: Jan 23, 2013
 *      Author: murilo
 */

#include "../include/SocketTCP.h"
#include "../include/Exceptions/SocketExceptions.hpp"
#include <cstdlib>
#include "../../Logger/include/Logger.h"

Socket_TCP::Socket_TCP(std::string host,std::string port) {
	this->host = host;
	this->port = port;
	memset(&sockType,0,sizeof(sockType));
	sockType.ai_family = AF_INET;
	sockType.ai_socktype = SOCK_STREAM;
	connected = false;
}

Socket_TCP::~Socket_TCP() {
	close(socketInfo);
}

void Socket_TCP::connectTo() {
	if(getaddrinfo(host.c_str(),port.c_str(),&sockType,&serverInfo) != 0){
		throw AddressException(host);
	}

	addrinfo *iter = serverInfo;
	for(;iter != NULL;iter = iter->ai_next){
		socketInfo = socket(iter->ai_family,iter->ai_socktype,iter->ai_protocol);
		if(socketInfo == -1){
			throw SocketException();
		}
		if(connect(socketInfo,iter->ai_addr,iter->ai_addrlen) == -1){
			close(socketInfo);
			continue;
		}
		break;
	}
	if(iter == NULL){
		throw ConnectionException();
	}
	freeaddrinfo(serverInfo);
	connected = true;
}


void Socket_TCP::sendMsg(std::string msg) {
	if(send(socketInfo,msg.c_str(),msg.size(),0) == -1){
		throw SendException(msg);
	}
}

std::string Socket_TCP::recvMsg() {
	char* msg,*msgAux;
	int rest;
	std::string msgReceived;

	u_int32_t msgSize = 0;
	 //u_int64_t msgSize = 0;

	int recvInfo = recv(socketInfo,((char*)&msgSize), sizeof(msgSize), 0); //recebe o tamanho do cabecalho inicial
	//LOG(log_Comunication)<<"Quantidade de Bytes do Prefixo "<<recvInfo;
	//std::cout<<"Tamanho mensan:"<<recvInfo<<std::endl;


	if(recvInfo == 0){
		connected = false;
	} else if(recvInfo == -1){
		throw ReceiveMessageException();
	}

	msgSize = ntohl(msgSize);//pega o tamanho da mensagem pela quantidade de bytes
	msg = new char[msgSize]; //instancia um vetor com quantidade de bytes

	//std::cout<<"Tamanho mensan:"<<msgSize<<std::endl;
	//LOG(log_Comunication)<<"Quantidade de Bytes para Receber "<<msgSize;

		if( (recvInfo = recv(socketInfo,msg,msgSize,0))== -1){
			if(recvInfo == 0){
				connected = false;
			}

		//	LOG(log_Comunication)<"ERRO NO SOCKET -1 ";
			throw ReceiveMessageException();
		}
		//LOG(log_Comunication)<<"Quantidade de Bytes Recebidos "<<recvInfo;
		msg[recvInfo-1] = '\0';

		if(recvInfo < msgSize)
		{

			msgAux = new char[msgSize - recvInfo];
			rest = msgSize - recvInfo;

			//LOG(log_Comunication)<<"Falta Receber "<<rest<< " Bytes";

			if( (recvInfo = recv(socketInfo,msgAux,rest,0))== -1)
			{
				if(recvInfo == 0){
					connected = false;
				}

				//LOG(log_Comunication)<"ERRO NO SOCKET -1 ";
				throw ReceiveMessageException();
			}

			//LOG(log_Comunication)<<"Bytes Recebidos que faltavam "<<recvInfo;

			msgAux[rest-1] = '\0';

			/*concatenando string*/
			std::ostringstream* c = new std::ostringstream;
			*c << msg<<msgAux<< std::ends;
			std::string mensCompleta = c->str().c_str();


			//msgReceived.append(std::string(msgAux));//recebe apenas final da string

			msgReceived.append(std::string(mensCompleta));
			//LOG(log_Comunication)<<"Mensagem 1 "<<msg;
			//LOG(log_Comunication)<<"Mensagem 2 "<<msgAux;

			//std::cout<<"Recebendo mensagem Maior"<<std::endl;

			delete[] msgAux;

		}else
		{
			//std::cout<<"Recebedo mensagem menor:"<<std::endl;
			msg[msgSize-1] = '\0';
			msgReceived.append(std::string(msg));
		}

	delete[] msg;

	return msgReceived;
}

std::string Socket_TCP::recvMsg(size_t size){

	char *msg = new char[size];
    std::string msgReceived;
	int recvInfo;

    if((recvInfo = recv(socketInfo,msg,size,0)) == -1){
    	if(recvInfo == 0){
			connected = false;
		}
		throw ReceiveMessageException();
	}

    msg[size] = '\0';
    std::cerr<<msg<<std::endl;
	msgReceived.append(std::string(msg));
	delete[] msg;
	//std::cerr<<msgReceived<<std::endl;

	return msgReceived;
}

bool Socket_TCP::isConnected() {
	return connected;
}



